import sys
import inspect
import os.path
import socket
from time import time
from threading import currentThread

os_path_separator = os.path.normcase('/')

def bytes_from_stream(stream):
    """yields the bytes of a stream one at a time"""
    next_char = stream.read(1)
    while next_char:
        yield next_char
        next_char = stream.read(1)

def get_ip_from_hostname(hostname):
    """given a hostname, returns the IP address for that hostname"""
    return socket.getaddrinfo(hostname, None)[0][4][0]

def absolute_directory_of_caller():
    """returns an absolute path to the code that called this method"""
    frames = inspect.getouterframes(inspect.currentframe())
    return os.path.abspath(os.path.dirname(frames[2][1]))

def absolute_directory_of_object(the_object):
    """given an object, returns an absolute path to the module
    that defined that object"""
    sourcefile = inspect.getsourcefile(the_object)
    abspath = os.path.abspath(sourcefile)
    return os.path.dirname(abspath)

def relative_path_between(from_path, to_path):
    """Return a relative path to the target from either the current dir or an optional base dir.
    Base can be a directory specified either as absolute or relative to current dir.
    
    author: richard barran
    source: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/302594"""
    
    target = to_path
    base = from_path

    if not os.path.exists(target):
        raise OSError, 'Target does not exist: '+target

    if not os.path.isdir(base):
        raise OSError, 'Base is not a directory or does not exist: '+base

    base_list = (os.path.abspath(base)).split(os.sep)
    target_list = (os.path.abspath(target)).split(os.sep)

    # On the windows platform the target may be on a completely different drive from the base.
    if os.name in ['nt','dos','os2'] and base_list[0] <> target_list[0]:
        raise OSError, 'Target is on a different drive to base. Target: '+target_list[0].upper()+', base: '+base_list[0].upper()

    # Starting from the filepath root, work out how much of the filepath is
    # shared by base and target.
    for i in range(min(len(base_list), len(target_list))):
        if base_list[i] <> target_list[i]: break
    else:
        # If we broke out of the loop, i is pointing to the first differing path elements.
        # If we didn't break out of the loop, i is pointing to identical path elements.
        # Increment i so that in all cases it points to the first differing path elements.
        i+=1

    rel_list = [os.pardir] * (len(base_list)-i) + target_list[i:]
    if len(rel_list) > 0:
        return os.path.join(*rel_list)
    else:
        return ""
